/**
 * Copyright 2008 Matthew DeLambo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.delambo.drool.pooling;

import com.delambo.drool.exceptions.DroolException;
import com.delambo.drool.modules.*;
import com.delambo.drool.utilities.*;
import com.delambo.drool.interfaces.*;
import com.google.inject.*;
import com.google.inject.name.*;
import java.sql.*;
import java.util.*;

/**
 * Client pool that is used for construction, deletion, and interfacing with 
 * pool(s).
 * @author delambo
 * @param K type of identifier for pools in pool map.
 * @param V type of pools.
 */
public final class Drool_Impl<K, V extends Pool> 
        implements Drool<K, V> {
    
    final private ImmutableMap<K, V> poolMap;
    
    public Drool_Impl(final ImmutableMap<K, V> pool_map) throws DroolException {
        this.poolMap = pool_map;
    }
    
    /**
     * Gets a connection from the pool with the given identifier.
     * @param k identifier for pool to grab connection from.
     * @return pooled connection.
     */
    public Connection getConnection(K key) throws DroolException {
        verifyPoolExists(key);
        return (Connection) poolMap.get(key).getResource();
    }
    
    /**
     * Returns a connection to the pool with the given identifier.
     * @param k identifier of pool to return to.
     * @param con borrowed connection.
     */
    public void returnConnection(K key, Connection con) throws DroolException {
        verifyPoolExists(key);
        poolMap.get(key).returnResource(con);
    }
    
    /**
     * Closes the given pool in the poolMap map.
     * @param k identifier of pool to close.
     */
    public void closePool(K key) throws DroolException {
        verifyPoolExists(key);
        close(key);
    }
    
    /**
     * Closes all of the poolMap in the poolMap map.
     */
    public void closeAllPools() {
        Iterator p = ((ImmutableMap) poolMap).keySet().iterator();
        while(p.hasNext()) {
            close((K) p.next());
        }
    }
    
    /**
     * Prints the current state of the pool with the given identifier to the 
     * pool log.
     * @param k identifier for pool to print.
     * @param location message about where print was invoked.
     * @throws com.delambo.drool.utilities.DroolException
     */
    public void printState(K key, String location) throws DroolException {
        verifyPoolExists(key);
        poolMap.get(key).printState(location);
    } 
    
    /**
     * Closes the pool with the given identifier.
     * @param k identifier of pool to close.
     */
    private void close(K key) {
        poolMap.get(key).closePool();
        Pool p = poolMap.get(key);
        p = null;
    }
    
    /**
     * Verifies that the pool with the given identifier exists in the poolMap.
     * @param k identifier of pool to verify.
     */
    private void verifyPoolExists(K key) throws DroolException {
        if(!poolMap.containsKey(key))
            throw new DroolException("Pool ID does not exist: " + key);
    }       
}
